﻿using CPF.Controls;
using CPF.Drawing;
using CPF.Input;

namespace ScottPlot.CPF;

public class CPFPlotMenu : IPlotMenu
{
    public string DefaultSaveImageFilename { get; set; } = "Plot.png";
    public List<ContextMenuItem> ContextMenuItems { get; set; } = new();
    private readonly CPFPlot ThisControl;

    public CPFPlotMenu(CPFPlot cpfPlot)
    {
        ThisControl = cpfPlot;
        Reset();
    }

    public ContextMenuItem[] GetDefaultContextMenuItems()
    {
        ContextMenuItem saveImage = new()
        {
            Label = "保存图片",
            OnInvoke = OpenSaveImageDialog
        };

        ContextMenuItem copyImage = new()
        {
            Label = "复制图片",
            OnInvoke = CopyImageToClipboard
        };

        ContextMenuItem autoscale = new()
        {
            Label = "自动缩放",
            OnInvoke = Autoscale,
        };

        return new ContextMenuItem[] {
            saveImage,
            copyImage,
            autoscale,
        };
    }

    public ContextMenu GetContextMenu(Plot plot)
    {
        ContextMenu menu = new();
        foreach (var curr in ContextMenuItems)
        {
            if (curr.IsSeparator)
            {
                menu.Items.Add(new Separator{});
            }
            else
            {
                var menuItem = new MenuItem() { Header = curr.Label };
                menuItem.Click += (s, e) => curr.OnInvoke(plot);
                menu.Items.Add(menuItem);
            }
        }

        return menu;
    }

    public readonly List<FileDialogFilter> FileDialogFilters = new()
    {
        new() { Name = "PNG Files", Extensions = "png" },
        new() { Name = "JPEG Files", Extensions = "jpg,jpeg" },
        new() { Name = "BMP Files", Extensions = "bmp" },
        new() { Name = "WebP Files", Extensions = "webp" },
        new() { Name = "SVG Files", Extensions = "svg" },
        new() { Name = "All Files", Extensions = "*" },
    };

    public async void OpenSaveImageDialog(Plot plot)
    {
        SaveFileDialog dialog = new();

        foreach (var curr in FileDialogFilters)
        {
            dialog.Filters.Add(curr);
        }
        var filename = await dialog.ShowAsync((Window)ThisControl.Root);
        if (string.IsNullOrEmpty(filename))
            return;
        
        // TODO: launch a pop-up window indicating if extension is invalid or save failed
        ImageFormat format = ImageFormats.FromFilename(filename);
        PixelSize lastRenderSize = plot.RenderManager.LastRender.FigureRect.Size;
        plot.Save(filename, (int)lastRenderSize.Width, (int)lastRenderSize.Height, format);
    }

    public void CopyImageToClipboard(Plot plot)
    {
        PixelSize lastRenderSize = plot.RenderManager.LastRender.FigureRect.Size;
        byte[] bytes = plot.GetImage((int)lastRenderSize.Width, (int)lastRenderSize.Height).GetImageBytes();
        MemoryStream ms = new(bytes);
        using Bitmap bmp = new(ms);
        Clipboard.SetData((DataFormat.Image, bmp));
    }

    public void Autoscale(Plot plot)
    {
        plot.Axes.AutoScale();
        ThisControl.Refresh();
    }

    public void ShowContextMenu(Pixel pixel)
    {
        Plot? plot = ThisControl.GetPlotAtPixel(pixel);
        if (plot is null)
            return;
        var menu = GetContextMenu(plot);
        ThisControl.ContextMenu = menu;
        //menu.Show(ThisControl, new Point((int)pixel.X, (int)pixel.Y));
    }

    public void Reset()
    {
        Clear();
        ContextMenuItems.AddRange(GetDefaultContextMenuItems());
    }

    public void Clear()
    {
        ContextMenuItems.Clear();
    }

    public void Add(string Label, Action<Plot> action)
    {
        ContextMenuItems.Add(new ContextMenuItem() { Label = Label, OnInvoke = action });
    }

    public void AddSeparator()
    {
        ContextMenuItems.Add(new ContextMenuItem() { IsSeparator = true });
    }
}
